<?php
/**
 * Subclass for representing a row from the 'calendar_entry' table.
 *
 * 
 *
 * @package lib.model
 */ 
class Calendar extends BaseCalendar
{

    const DAY                   = 'd';
    const MONTH                 = 'm';
    const YEAR                  = 'y';
    const WEEK                  = 'w';
    
    /**
     * 
     * returns cout events of one same sequence
     * @param string $seq
     */
    public function countSeqEvents()
    {
        $c = new Criteria();
        $c->add(CalendarPeer::SEQ_ID, $this->getSeqId());
        $arEvents = CalendarPeer::doSelect($c);
        return count($arEvents);
    }
    /**
     * 
     * returns array of constants with names
     */
    public static function getTimeMetricList()
    {
        return array(
            self::DAY => sfContext::getInstance()->getI18n()->__('Days')
            , self::WEEK => sfContext::getInstance()->getI18n()->__('Weeks')
            , self::MONTH => sfContext::getInstance()->getI18n()->__('Months')
            , self::YEAR => sfContext::getInstance()->getI18n()->__('Years')
        );
    }
    public static function getTimeMetricListSeconds()
    {
        return array(
            self::DAY => 60 * 60 * 24
            , self::WEEK => 60 * 60 * 24 * 7
            , self::MONTH => 60 * 60 * 24 * 30
            , self::YEAR => 60 * 60 * 24 * 346
        );
    }
    public function getGeoName()
    {
        $name = '';
        if( $this->geo_name_id > 0 )
        {
            $name = GeoName::getById($this->geo_name_id)->getName();
        }
        
        return $name;
    }
    /**
     * 
     * returns int, count of days events
     * @param timestamp $FirstTm
     */
    public static function countDayEvents($FirstTm)
    {
        return rand(0, 10);
    }
    public function hydrate(ResultSet $rs, $startcol = 1)
    {
        $this->setCulture(sfContext::getInstance()->getUser()->getCulture());
        parent::hydrate($rs, $startcol);
    }
    
    /**
     * 
     * creates new Object
     * @param int $statusId
     * @param int $userId
     * @param int $personId
     * @param varchar $userRoles
     * @param int $isPersonal
     * @param int $geoId
     * @param carchar $title
     * @param carchar $culture
     * @param unknown_type $name
     * @param unknown_type $description
     * @param tm $startAt
     * @param tm $endsAt
     */
    public static function createNew($statusId, $seq, $userId, $personId, $userRoles, $isPersonal, $geoId, $title, $culture, $name, $description, $duration, $durationMetric, $timesToRepeat, $startAt, $endsAt = null )
    {
        $event = new Calendar();
        $event->setSeqId($seq);
        $event->setStatusId($statusId);
        $event->setUserId($userId);
        $event->setPersonId($personId);
        $event->setUserRoles($userRoles);
        $event->setIsPersonal($isPersonal);
        $event->setTitle($title);
        $event->setCulture($culture );
        $event->setGeoNameId($geoId);
        $event->setName($name);
        $event->setDescription($description);
        $event->setDuration($duration);
        $event->setDurationMetric($durationMetric);
        $event->setTimesToRepeat($timesToRepeat);
        $event->setStartAt(date('Y-m-d H:i:s',$startAt));
        if( $endsAt )
        {
            $event->setEndsAt(date('Y-m-d H:i:s',$endsAt));
        }
        $event->save();
    }
    
    /*
     * get events from calendar
     * @params
     * date yyyy-mm-dd
     * duration - number of days
     * 
     * return object 
     */
    public static function getEventsAll($date, $duration)
    {
        //debugvar($date, 'date');
        //debugvar($duration);
        try {
            // check date
            $arDateTime = explode(' ', $date);
            if( count($arDateTime) > 2 )
            {
                throw new Exception('Error: missing date ' . $date . ' ' . $arDateTime[0] . '|' . $arDateTime[1]. ' ' . count($arDateTime) );
            }
            
            $arDate = explode('-', $arDateTime[0]);
            if( count($arDate) != 3 )
            {
                throw new Exception('Error: missing date ' . $date);
            }
            
            // check year
            if( !is_numeric($arDate[0]) || ($arDate[0] <= 0 || $arDate[0] >= 9999 ) )
            {
                throw new Exception('Error: missing year ' . $arDate[0]);
            }
            // check month
            if( !is_numeric($arDate[1]) || ($arDate[0] < 1 || $arDate[1] > 12 ) )
            {
                throw new Exception('Error: missing month ' . $arDate[1]);
            }
            // check day
            if( !is_numeric($arDate[2]) || ($arDate[2] < 1 || $arDate[2] > 31 ) )
            {
                throw new Exception('Error: missing day ' . $arDate[2]);
            }
            
            // check day
            if( !is_numeric($duration) )
            {
                throw new Exception('Error: missing duration ' . $duration);
            }
            
            $dateEnd = date('Y-m-d', strtotime(date('Y-m-d', strtotime($date)) . ' +' . ($duration-1) . ' day') );
            
            $c = new Criteria();
            /*
            $c1 = $c->getNewCriterion(CalendarEntryPeer::START_AT, $dateEnd . ' 23:59:59', Criteria::LESS_EQUAL);
            $c2 = $c->getNewCriterion(CalendarEntryPeer::ENDS_AT, $date . ' 00:00:00', Criteria::GREATER_EQUAL);
            $c3 = $c->getNewCriterion(CalendarEntryPeer::ENDS_AT, null, Criteria::ISNULL);
            $c2->addOr($c3);
            $c1->addAnd($c2);
            */
            $c1 = $c->getNewCriterion(CalendarPeer::START_AT, $dateEnd . ' 23:59:59', Criteria::LESS_EQUAL);
            $c2 = $c->getNewCriterion(CalendarPeer::START_AT, $date . ' 00:00:00', Criteria::GREATER_EQUAL);
            $c->add($c1);
            $c->addAnd($c2);
            $c->addAscendingOrderByColumn(CalendarPeer::START_AT);
            
            $entry = CalendarPeer::doSelect($c);
            
            return $entry;
        }
        catch (Exeption $e)
        {
            $this->message = $e->getMessage();
            $this->setTemplate('response');
            return null;
        }
        
        //debugvar($entry, 'entry -lib');
        
    }
    

    /*
     * get events from calendar for year, month
     * @params
     * year yyyy
     * month mm
     * 
     * return object 
     */
    public static function getMonthEvents($year, $month)
    {
        return self::getEventsAll($year . '-' . $month . '-01', date('t', strtotime($year . '-' . $month . '-01')));
    }
    
    /*
     * get count events from calendar for date
     * @params
     * date - yyyy-m-d
     * 
     * return number 
     */
    public static function getCountEvents($date)
    {
        $events = self::getEventsAll($date, 0);
        
        // count events of date
        $iCount = 0;
        
        if( !is_null($events) )
        {
            foreach( $events as $event )
            {
                $iCount++;
                //debugvar($iCount, 'iCount');
                //debugvar($event, 'event');
            }
        }
        return $iCount;
    }
    /**
     * 
     * creates all repeated events (times to repeat)
     * @param object $calendar
     * @throws Exception if duration not set
     */
    public static function createRepeatedEvents($calendar, $seq, $dateBegin)
    {
        /* @var $calendar Calendar */
        if( $calendar->getTimesToRepeat() > 0 )
                {
                    // for day and week can be constants to tm added
                    if( ($calendar->getDurationMetric() == Calendar::DAY) || ($calendar->getDurationMetric() == Calendar::WEEK) )
                    {
                        $arSec = Calendar::getTimeMetricListSeconds();
                        // duration metric (week or day) multiply with duration (time in seconds)
                        $seconds = $arSec[$calendar->getDurationMetric()] * $calendar->getDuration();
                        $tm = strtotime($dateBegin);
                        if( $seconds > 0 )
                        {
                            // creates all (timeToRepeat) events
                            for( $i = 0; $i< $calendar->getTimesToRepeat(); $i++ )
                            {
                                // tm increased
                                $tm2 = $tm + ( $seconds * $i);
                                Calendar::createNew(MyConstants::STATUS_APPROVED
                                                    , $seq
                                                    , get_user_id()
                                                    , ''
                                                    , $calendar->getUserRoles()
                                                    , $calendar->getIsPersonal()?1:0 
                                                    , $calendar->getGeoNameId()
                                                    , $calendar->getTitle()
                                                    , sfContext::getInstance()->getUser()->getCulture()
                                                    , $calendar->getName()
                                                    , $calendar->getDescription()
                                                    , $calendar->getDuration()
                                                    , $calendar->getDurationMetric()
                                                    , $calendar->getTimesToRepeat()
                                                    , $tm2);
                            }
                        }
                    }elseif( $calendar->getDurationMetric() == Calendar::MONTH )
                    // if metric is month
                    {
                        if($calendar->getDuration() > 0 )
                        {
                            $tm = strtotime($dateBegin);
                            
                            $month = date('n', $tm);
                            $year = date('Y', $tm);
                            $day = date('j', $tm);
                            $time = date('H:i:s');
                            // creates all (timeToRepeat) events
                            for( $i = 0; $i< $calendar->getTimesToRepeat(); $i++ )
                            {
                                if( $i > 0 )
                                {
                                    $month = $month + $calendar->getDuration();
                                }
                                
                                if( $month > 12 )
                                {
                                    $year = $year + 1;
                                    $month = 1;
                                }
                                // if month dont have 31 day, last month`s day will be set
                                $frmt = $year . '-' . $month;
                                $tmDaysCnt = strtotime($frmt, $tm);
                                if( date('t', $tmDaysCnt) < $day )
                                {
                                    $format = $year . '-' . $month . '-' . date('t', $tmDaysCnt) . ' ' . $time;
                                }else 
                                {
                                    $format = $year . '-' . $month . '-' . $day . ' ' . $time;
                                }
                                
                                $tmNew = strtotime($format, $tm);
                                Calendar::createNew(MyConstants::STATUS_APPROVED
                                                    , $seq
                                                    , get_user_id()
                                                    , ''
                                                    , $calendar->getUserRoles()
                                                    , $calendar->getIsPersonal()?1:0 
                                                    , $calendar->getGeoNameId()
                                                    , $calendar->getTitle()
                                                    , sfContext::getInstance()->getUser()->getCulture()
                                                    , $calendar->getName()
                                                    , $calendar->getDescription()
                                                    , $calendar->getDuration()
                                                    , $calendar->getDurationMetric()
                                                    , $calendar->getTimesToRepeat()
                                                    , $tmNew);
                            }
                        }
                    }elseif( $calendar->getDurationMetric() == Calendar::YEAR )
                    {
                        if($calendar->getDuration() > 0 )
                        {
                            $tm = strtotime($dateBegin);
                            $month = date('n', $tm);
                            $year = date('Y', $tm);
                            $day = date('j', $tm);
                            $time = date('H:i:s');
                            for( $i = 0; $i< $calendar->getTimesToRepeat(); $i++ )
                            {
                                $year2 = $year + ($calendar->getDuration()*$i);
                                $format = $year2 . '-' . $month . '-' . $day . ' ' . $time;
                                $tmNew = strtotime($format, $tm);
                                // if month dont have 31 day, last month`s day will be set
                                $frmt = $year . '-' . $month;
                                $tmDaysCnt = strtotime($frmt, $tm);
                                if( date('t', $tmDaysCnt) < $day )
                                {
                                    $format = $year2 . '-' . $month . '-' . date('t', $tmDaysCnt) . ' ' . $time;
                                    $tmNew = strtotime($format, $tm);
                                }
                                Calendar::createNew(MyConstants::STATUS_APPROVED
                                                    , $seq
                                                    , get_user_id()
                                                    , ''
                                                    , $calendar->getUserRoles()
                                                    , $calendar->getIsPersonal()?1:0 
                                                    , $calendar->getGeoNameId()
                                                    , $calendar->getTitle()
                                                    , sfContext::getInstance()->getUser()->getCulture()
                                                    , $calendar->getName()
                                                    , $calendar->getDescription()
                                                    , $calendar->getDuration()
                                                    , $calendar->getDurationMetric()
                                                    , $calendar->getTimesToRepeat()
                                                    , $tmNew);
                            }
                        }
                    }else 
                    {
                        throw new Exception('Duration metric not set.');
                    }
                }
    }
    /**
     * 
     * deletes all events by squence code
     * @param string $seq
     */
    public static function deleteBySeq($seq)
    {
        $c = new Criteria();
        $c->add(CalendarPeer::SEQ_ID, $seq);
        $arEvents = CalendarPeer::doSelect($c);
        foreach( $arEvents as $event )
        {
            $event->delete();
        }
    }
    /**
     * if event from sequence, reduce cequence events count by deleting
     * @see BaseCalendar::delete()
     */
    public function delete($con = null)
    {
        /* @var $first Calendar */
        $seq = $this->getSeqId();
        if($seq != '')
        {
            $c = new Criteria();
            $c->add(CalendarPeer::SEQ_ID, $seq);
            $arEvents = CalendarPeer::doSelect($c);
            foreach( $arEvents as $event )
            {
                $event->setTimesToRepeat($event->getTimesToRepeat() - 1);
                $event->save();
            }
        }
        parent::delete($con);
    }
  public function getFirstEventStart()
  {
      $c = new Criteria();
      $c->add(CalendarPeer::SEQ_ID, $this->getSeqId());
      $c->addAscendingOrderByColumn(CalendarPeer::START_AT);
      $first = CalendarPeer::doSelectOne($c);
      $start = null;
      if($first)
      {
          $start = $first->getStartAt();
      }
      return $start;
  }
}
